package fhfl.mobapp.belastungstest.mobapp_belastungstest;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.CheckBox;
import android.graphics.Paint;


import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.LineChart;
import org.achartengine.chart.ScatterChart;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.XYSeries;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import org.achartengine.chart.CombinedXYChart.XYCombinedChartDef;

import java.net.*;
import java.util.ArrayList;

import fhfl.mobapp.belastungstest.mobapp_communicate.SendUDPThread;
import fhfl.mobapp.belastungstest.mobapp_communicate.ReceiveUDPThread;

public class MainActivity extends Activity
{
    final Activity main = this;
    //var operate
    //time measure var for startsend
    float stime;
    float tdifference;
    //var surface
    private EditText adresse;
    private EditText port;
    private Button startsend;
    private Button stopsend;
    private CheckBox endlessloop;
    private TextView transmittedkbytes;
    private TextView otransmittedkbytes;
    private SeekBar seekbarps;
    private TextView packetsize;
    private TextView latency;
    private SeekBar seekbarms;
    private TextView packetinterval;
    private TextView olatency;
    private ScrollView sv;
    private TextView debug;
    private TextView timerun;
    private long time = System.currentTimeMillis();
    private static final String TAG = "MainActivity";
    //chart
    private GraphicalView mChartView;
    private XYMultipleSeriesDataset dataset;
    private XYMultipleSeriesRenderer renderer;
    //chart array
    ArrayList <Integer> alatency = new ArrayList<Integer>();
    ArrayList <Integer> atransmittedkbytes = new ArrayList<Integer>();
    ArrayList <Double> atime = new ArrayList<Double>();
    //CommunicationsThreads
    SendUDPThread sendThread = null;
    ReceiveUDPThread receiveThread = null;
    //Gesammtwerte
    private long receivedBytes = 0;
    //interface
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d(TAG, "onCreate() wurde aufgerufen");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //var init
        stime = 0f;
        tdifference = 0f;
        //surface inits
        adresse = (EditText) findViewById(R.id.editAdresse);
        port = (EditText) findViewById(R.id.editPort);
        startsend = (Button) findViewById(R.id.startsend);
        stopsend = (Button) findViewById(R.id.stopsend);
        endlessloop = (CheckBox) findViewById(R.id.checkboxendlessloop);
        transmittedkbytes = (TextView) findViewById(R.id.transmittedkbytes);
        otransmittedkbytes = (TextView) findViewById(R.id.otransmittedkbytes);
        seekbarps = (SeekBar) findViewById(R.id.seekbarpacketsize);
        packetsize = (TextView) findViewById(R.id.packetsize);
        latency = (TextView) findViewById(R.id.latency);
        olatency = (TextView) findViewById(R.id.olatency);
        seekbarms = (SeekBar) findViewById(R.id.seekbarpacketinterval);
        packetinterval = (TextView) findViewById(R.id.packetinterval);
        ScrollView sv = (ScrollView)findViewById(R.id.scrolldebug);
        debug = (TextView) findViewById(R.id.debugbox);
        timerun = (TextView) findViewById(R.id.timerun);
        //listen
        startsend.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view)
            {
                stime = System.currentTimeMillis();
                seekbarps.setEnabled(false);
                seekbarms.setEnabled(false);
                startsend.setEnabled(false);
                stopsend.setEnabled(true);
                endlessloop.setEnabled(false);
                try
                {
                    if(sendThread == null)
                        sendThread = new SendUDPThread(InetAddress.getByName(adresse.getText().toString()), Integer.parseInt(port.getText().toString()), getPacketSize(), getPacketInterval());

                    if (receiveThread == null)
                        receiveThread = new ReceiveUDPThread(Integer.parseInt(port.getText().toString()), main);

                    sendThread.start();
                    receiveThread.start();

                    if(!endlessloop.isChecked())
                    {
                        sendThread.finish();
                        receiveThread.finish();

                        sendThread = null;
                        receiveThread = null;

                        seekbarps.setEnabled(true);
                        seekbarms.setEnabled(true);
                        startsend.setEnabled(true);
                        stopsend.setEnabled(false);
                        startsend.setEnabled(true);
                        endlessloop.setEnabled(true);
                    }
                } catch (Exception e)
                {
                    Toast.makeText(MainActivity.this, "[ERROR] " + e.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }
        });
        stopsend.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                seekbarps.setEnabled(true);
                seekbarms.setEnabled(true);
                startsend.setEnabled(true);
                stopsend.setEnabled(false);
                startsend.setEnabled(true);
                endlessloop.setEnabled(true);
                try
                {
                    sendThread.finish();
                    receiveThread.finish();
                    sendThread = null;
                    receiveThread = null;

                } catch (Exception e) {
                    Toast.makeText(MainActivity.this, "[ERROR] " + e.getMessage(), Toast.LENGTH_SHORT).show();
                }
            }
        });
        seekbarps.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                packetsize.setText(String.valueOf(progress * 10.24));
                if (progress==0) packetsize.setText("1");
            }
            //default:
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {}
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {}
        });

        seekbarms.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                packetinterval.setText(String.valueOf(progress * 10));
                if (progress==0) packetinterval.setText("10");
            }
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {}
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {}
        });
    }
    //data input
    public void updateData(int ulatency, int usizePacket, int upacketNumber )
    {
        //debug
        try
        {
            debug.append("latency: "+ String.valueOf(ulatency)+"\n"+
                         "packetsize: "+ String.valueOf(usizePacket)+"\n"+
                         " packetnumber: "+ String.valueOf(upacketNumber)+"\n");
            scrollToBottom();
        }
        catch(Exception e)
        {
            debug.append("Error: "+e+"\n");
            //scrollToBottom();
        }
        Toast.makeText(this,"Empfangen",Toast.LENGTH_SHORT).show();
        //set value @interface
        latency.setText(String.valueOf(ulatency)+" ms");
        transmittedkbytes.setText(String.valueOf(usizePacket)+" kbyte");
        timerun.setText(String.valueOf(System.currentTimeMillis()-time)+" ms");
        //add to array
        alatency.add(Integer.parseInt(String.valueOf(ulatency)));
        atransmittedkbytes.add(Integer.parseInt(String.valueOf(ulatency)));
        atime.add(Double.valueOf(System.currentTimeMillis() - time));
        //debug, dosnt work so far
        /*
        try
        {
            debug.append("alatency: "+String.valueOf(alatency.get(alatency.size()))+"\n"+
                    "apacketsize: "+String.valueOf(atransmittedkbytes.get(alatency.size()))+"\n"+
                    "apacketnumber: "+String.valueOf(atime.get(alatency.size())) +"\n");
            scrollToBottom();
        }
        catch(Exception e)
        {
            debug.append("Error: "+e+"\n");
            //scrollToBottom();
        }
        */
        //diagrammdraw
        newData();
    }
    //scrolldwon void
    private void scrollToBottom() {
        sv.post(new Runnable() {
            public void run() {
                sv.smoothScrollTo(0, sv.getBottom());
            }
        });
    }
    //diagramm demo...
    protected void newData()
    {

        //testarray
        int[]x={1,2,3,4,5,6,7,8,9,10};
        int[]y={30,34,45,57,77,89,199,111,123,145};
        int[]x2 = {1,2,3,4,5,6,7,8,9,10};
        int[]y2 = {39,145,35,87,2,65,48,49,100,106};
        if (mChartView == null)
        {
            LinearLayout layout = (LinearLayout) findViewById(R.id.chart);
            //input diagramm
            XYSeries dbytes = new XYSeries("kbyte/sec",0);
            XYSeries dlatency = new XYSeries("latency/sec",1);
            XYSeries dobytes = new XYSeries("obytes",2);
            //xmax for obytes/latency
            int xmax = atime.size();
            /*
            for(int i=0; i<xmax;i++) dbytes.add(atime.get(i), atransmittedkbytes.get(i));
            for(int i=0; i<xmax;i++) dlatency.add(atime.get(i),alatency.get(i));
            */
            if(x.length>=x2.length) xmax = x.length; else xmax=x2.length;
            for(int i=0; i<x.length;i++) dbytes.add(x[i], y[i]);
            for(int i=0; i<x2.length;i++) dlatency.add(x2[i],y2[i]);

            //obytes
            dobytes.add(0,Integer.parseInt(otransmittedkbytes.getText().toString()));
            dobytes.add(xmax,Integer.parseInt(otransmittedkbytes.getText().toString()));
            //generate dataset
            XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
            dataset.addSeries(0, dbytes);
            dataset.addSeries(1, dlatency);
            dataset.addSeries(2, dobytes);
            //first graph for bytes
            XYSeriesRenderer renderer = new XYSeriesRenderer();
            //graph render:
            renderer.setDisplayBoundingPoints(true);
            renderer.setPointStrokeWidth(1);
            renderer.setLineWidth(3);
            renderer.setDisplayBoundingPoints(true);
            renderer.setColor(Color.rgb(255, 196, 88));
            renderer.setPointStyle(PointStyle.CIRCLE);
            renderer.setFillPoints(true);
            renderer.setChartValuesSpacing(10f);
            //second graph for latency
            XYSeriesRenderer renderer2 = new XYSeriesRenderer();
            //graph render2:
            renderer2.setPointStrokeWidth(3);
            renderer2.setDisplayBoundingPoints(true);
            renderer2.setColor(Color.BLUE);
            renderer2.setPointStyle(PointStyle.CIRCLE);
            renderer2.setFillPoints(true);
            //third graph for obytes
            XYSeriesRenderer renderer3 = new XYSeriesRenderer();
            //graph render3:
            renderer3.setPointStrokeWidth(1);
            renderer3.setDisplayBoundingPoints(true);
            renderer3.setColor(Color.RED);
            renderer3.setPointStyle(PointStyle.CIRCLE);
            renderer3.setFillPoints(true);
            //build graph1+2
            XYMultipleSeriesRenderer mRenderer = new XYMultipleSeriesRenderer(3);
            mRenderer.addSeriesRenderer(renderer);
            mRenderer.addSeriesRenderer(renderer2);
            mRenderer.addSeriesRenderer(renderer3);
            //diagramm render:
            //color
            mRenderer.setApplyBackgroundColor(true);
            mRenderer.setBackgroundColor(Color.WHITE);
            mRenderer.setMarginsColor(Color.WHITE);
            mRenderer.setLabelsColor(Color.BLACK);
            //axes
            mRenderer.setYAxisMin(0,0);
            mRenderer.setYAxisMin(0,1);
            mRenderer.setYAxisMin(0,2);
            mRenderer.setAxesColor(Color.BLACK);
            mRenderer.setAxisTitleTextSize(15f);
            mRenderer.setYAxisAlign(Paint.Align.LEFT,0);
            mRenderer.setYAxisAlign(Paint.Align.RIGHT, 1);
            mRenderer.setYAxisAlign(Paint.Align.LEFT,2);
            //label
            mRenderer.setLabelsColor(Color.BLACK);
            mRenderer.setLabelsTextSize(15f);
            //grid:
            mRenderer.setShowGrid(false);
            mRenderer.setGridColor(Color.GRAY);
            //text:
            mRenderer.setChartTitle("");
            mRenderer.setYTitle("data in bytes",0);
            mRenderer.setYTitle("latency in ms",1);
            mRenderer.setXTitle("time in s");
            //zoom:
            mRenderer.setZoomEnabled(true);
            mRenderer.setZoomButtonsVisible(true);
            //merge in one def.
            XYCombinedChartDef[] types =new XYCombinedChartDef[]
                    {
                            new XYCombinedChartDef(LineChart.TYPE,0),
                            new XYCombinedChartDef(ScatterChart.TYPE,1),
                            new XYCombinedChartDef(LineChart.TYPE,2)
                    };
            //creating a combined chart
            mChartView = (GraphicalView) ChartFactory.getCombinedXYChartView(MainActivity.this, dataset, mRenderer, (types));
            //output
            layout.addView(mChartView);
        }
        else
        {
            //repaint if new data
            mChartView.repaint();
        }
    }
    public int getPacketSize()
    {
        String bytes = packetsize.getText().toString();
        int n;
        if(bytes.matches("\\d+")) //check if only digits.
        {
            n = Integer.parseInt(bytes) * 1024;
        }
        else
        {
            return 1 * 1024;
        }
        return n;
    }
    public int getPacketInterval()
    {
        String interval = packetinterval.getText().toString();
        //check if only digits.
        if (interval.matches("\\d+"))
            return (Integer.parseInt(interval)*100);
        else
            return 1000;
    }
}